package br.trainee.web.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.UserTransaction;

import br.trainee.web.dao.service.IClinicaDAO;
import br.trainee.web.util.UtilFuncoes;
import br.trainee.web.vo.ClinicaTelefoneClinicaVO;
import br.trainee.web.vo.ClinicaVO;
import br.trainee.web.vo.EmailClinicaVO;
import br.trainee.web.vo.EnderecoClinicaVO;
import br.trainee.web.vo.TelefoneClinicaVO;

@RequestScoped
public class ClinicaDAOImpl extends EntityDAOImpl<ClinicaVO, Long> implements IClinicaDAO{
	
	@PersistenceContext(unitName="WebJsf")
	private EntityManager em;
	
	@Resource
	private UserTransaction userTransaction;
	
	public ClinicaDAOImpl() {
		
		super(ClinicaVO.class);
	}
	
	public ClinicaVO detalharClinica(Long idClinica) throws Exception{
		
		ClinicaVO clinica = new ClinicaVO();
		
		try{
			
				clinica.setEmails(consultarEmailPorIdClinica(idClinica));
				clinica.setEnderecos(consultarEnderecoPorIdClinica(idClinica));
				clinica.setListaTelefones(consultarTelefonePorIdClinica(idClinica));
				
		}
		catch(NoResultException e){
			
			clinica = null;
		}
		
		return clinica;
	}
	
	@Override
	public List<EmailClinicaVO> consultarEmailPorIdClinica(Long idClinica) throws Exception{
		
		List<EmailClinicaVO> listaEmails = null;
		
		try{
			
			userTransaction.begin();
			
				Query query = em.createNamedQuery("queryBuscarEmailPorIdClinica");
				
				query.setParameter("idClinica", idClinica);
				query.setParameter("tipoStatus", UtilFuncoes.TIPO_STATUS_ATIVO);
				
				listaEmails = query.getResultList();
			
			userTransaction.commit();
		}
		catch(NoResultException e){
			
			listaEmails = null;
		}
		
		return listaEmails;
	}
	
	@Override
	public List<EnderecoClinicaVO> consultarEnderecoPorIdClinica(Long idClinica) throws Exception{
		
		List<EnderecoClinicaVO> listaEnderecos = null;
		
		try{
			
			userTransaction.begin();
			
				Query query = em.createNamedQuery("queryBuscarEnderecoPorIdClinica");
				
				query.setParameter("idClinica", idClinica);
				query.setParameter("tipoStatus", UtilFuncoes.TIPO_STATUS_ATIVO);
				
				listaEnderecos = query.getResultList();
				
			userTransaction.commit();
		}
		catch(NoResultException e){
			
			listaEnderecos = null;
		}
		
		return listaEnderecos;
	}
	
	@Override
	public List<TelefoneClinicaVO> consultarTelefonePorIdClinica(Long idClinica) throws Exception{
		
		List<ClinicaTelefoneClinicaVO> listaClinicaTelefone = null;
		List<TelefoneClinicaVO> listaTelefones = new ArrayList<TelefoneClinicaVO>();
		
		try{
			
			userTransaction.begin();
			
				Query query = em.createNamedQuery("queryBuscarTelefonePorIdClinica");
				query.setParameter("idClinica", idClinica);
				query.setParameter("tipoStatus", UtilFuncoes.TIPO_STATUS_ATIVO);
				
				listaClinicaTelefone = query.getResultList();
				
				for (ClinicaTelefoneClinicaVO ct : listaClinicaTelefone) {
					
					TelefoneClinicaVO telefone = new TelefoneClinicaVO();
					
					telefone = ct.getTelefone();
					listaTelefones.add(telefone);
				}
			
			userTransaction.commit();
		}
		catch(NoResultException e){
			
			listaTelefones = null;
		}
		
		return listaTelefones;
	}
	
	public TelefoneClinicaVO buscarTelefonePorNumeroEDdd(TelefoneClinicaVO telefone) throws Exception{
		
		TelefoneClinicaVO telefoneSaida = null;
		
		try{
			
			Query query = em.createNamedQuery("queryBuscarTelefonePorNumeroEDdd");
			
			query.setParameter("telefoneClinica", telefone.getTelefoneClinica());
			query.setParameter("dddClinica", telefone.getDddClinica());
			
			telefoneSaida = (TelefoneClinicaVO) query.getSingleResult();
			
		}
		catch(NoResultException e){
			
			telefoneSaida = null;
		}
		
		return telefoneSaida;
	}
	
	@Override
	public void incluir(ClinicaVO clinica) throws Exception {
		
		userTransaction.begin();
			
			em.persist(clinica);
			
			for(ClinicaTelefoneClinicaVO ct: clinica.getListaClinicaTelefone()){
				
				ct.setClinica(clinica);
				
				TelefoneClinicaVO telefone = buscarTelefonePorNumeroEDdd(ct.getTelefone());
				
				if(telefone == null){
					
					em.persist(ct.getTelefone());
				}
				else{
					
					ct.setTelefone(telefone);
				}
				
				em.persist(ct);
			}
		
		userTransaction.commit();
	}

	@Override
	public EntityManager getEntityManager() {
		
		return this.em;
	}

	@Override
	public UserTransaction getUserTransaction() {

		return this.userTransaction;
	}
	
	@Override
	public void alterar(ClinicaVO clinica) throws Exception {
		userTransaction.begin();
			
			List<ClinicaTelefoneClinicaVO> listaCt = clinica.getListaClinicaTelefone();
			List<TelefoneClinicaVO> listaTelefoneAuxExc = clinica.getListaTelefoneAuxExc();
			List<EnderecoClinicaVO> listaEnderecoAuxInc = clinica.getListaEnderecoAuxInc();
			List<EnderecoClinicaVO> listaEnderecoAuxExc = clinica.getListaEnderecoAuxExc();
			List<EmailClinicaVO> listaEmailAuxInc = clinica.getListaEmailAuxInc();
			List<EmailClinicaVO> listaEmailAuxExc = clinica.getListaEmailAuxExc();
			
			clinica.setListaClinicaTelefone(null);
			
			ClinicaVO clinicaRetorno = em.merge(clinica);
		
			excluirEmailAux(listaEmailAuxExc);
			incluirEmailAux(listaEmailAuxInc);
			excluirEnderecoAux(listaEnderecoAuxExc);
			incluirEnderecoAux(listaEnderecoAuxInc);
			excluirTelefoneAux(listaTelefoneAuxExc);
			incluirTelefoneAux(clinicaRetorno, listaCt);
			
		userTransaction.commit();
	}
	
	private void excluirEmailAux(List<EmailClinicaVO> listaEmails) throws Exception{
		
		for (EmailClinicaVO emailClinica : listaEmails) {
			
			Query query = em.createQuery("update EmailClinicaVO set status =:status where idEmailClinica =:id");
			query.setParameter("status", emailClinica.getStatus());
			query.setParameter("id", emailClinica.getIdEmailClinica());
			
			if(emailClinica.getIdEmailClinica() != null){

				query.executeUpdate();
			}
		}
		
	}
	
	private void incluirEmailAux(List<EmailClinicaVO> listaEmails) throws Exception{
		if(listaEmails != null){
			
			for (EmailClinicaVO emailClinica : listaEmails) {
				
				em.persist(emailClinica);
			}	
		}
	
	}
	
	private void excluirEnderecoAux(List<EnderecoClinicaVO> listaEnderecos) throws Exception{
		
		for (EnderecoClinicaVO enderecoClinica : listaEnderecos) {
			
			Query query = em.createQuery("update EnderecoClinicaVO set status =:status where idEnderecoClinica =:id");
			query.setParameter("status", enderecoClinica.getStatus());
			query.setParameter("id", enderecoClinica.getIdEnderecoClinica());
			
			if(enderecoClinica.getIdEnderecoClinica() != null){
				
				query.executeUpdate();
			}
		}
	}
	
	private void incluirEnderecoAux(List<EnderecoClinicaVO> listaEnderecos) throws Exception{
		if(listaEnderecos != null){
			
			for (EnderecoClinicaVO enderecoClinica : listaEnderecos) {
				
				em.persist(enderecoClinica);
			}
		}	
	}
	
	private void excluirTelefoneAux(List<TelefoneClinicaVO> listaTelefones) throws Exception{
		
		for (TelefoneClinicaVO telefoneClinica : listaTelefones) {
			
			Query query = em.createQuery("update TelefoneClinicaVO set status =:status where idTelefoneClinica =:id");
			query.setParameter("status", telefoneClinica.getStatus());
			query.setParameter("id", telefoneClinica.getIdTelefoneClinica());
			
			if(telefoneClinica.getIdTelefoneClinica() != null){
				
				query.executeUpdate();
			}
		}
	}
	
	private void incluirTelefoneAux(ClinicaVO clinica, List<ClinicaTelefoneClinicaVO> listaCT) throws Exception{
		
		if(listaCT != null){
			
			for (ClinicaTelefoneClinicaVO ct : listaCT) {
				
				TelefoneClinicaVO tel = buscarTelefonePorNumeroEDdd(ct.getTelefone());
				
				if(tel == null){
					
					em.persist(ct.getTelefone());
				}
				else{
					
					ct.setTelefone(tel);
				}
			
				//ClinicaVO clinicaTeste = em.find(ClinicaVO.class, 5l);
				//TelefoneClinicaVO telefoneTeste = em.find(TelefoneClinicaVO.class, 15l);
				
				ct.setClinica(clinica);
				
				em.persist(ct);
			}
		}
	}
	@Override
	public List<ClinicaVO> consultarClinicaPorNome(String nomeClinica) throws Exception {
		
		userTransaction.begin();
		
			Query query = em.createNamedQuery("queryBuscarClinicaPorNome");
		
			query.setParameter("nome", "%" + nomeClinica.toLowerCase()+"%");
		
			List<ClinicaVO> listaClinicas = query.getResultList();
	
		userTransaction.commit();
	
		return listaClinicas;
	}

	@Override
	public List<ClinicaVO> consultarClinicaPorNomeECnpj(String nomeClinica, String cnpj) throws Exception {
		
		List<ClinicaVO> listaClinicas = null;
		
		try{
			userTransaction.begin();
			
				Query query = em.createNamedQuery("queryBuscarClinicaPorNomeECnpj");
				query.setParameter("nome", nomeClinica.toLowerCase() + "%");
				query.setParameter("cnpj", cnpj);
				query.setParameter("tipoStatus", UtilFuncoes.TIPO_STATUS_ATIVO);
				
				listaClinicas = query.getResultList();
				
			userTransaction.commit();
		}
		catch(NoResultException e){
			
			listaClinicas = null;
		}
		
		return listaClinicas;
	}

	@Override
	public boolean atlerarEmailClinica(EmailClinicaVO email) throws Exception {
		
		userTransaction.begin();
		
			/*Query query = em.createQuery("update EmailClinicaVO e set e.emailClinica =:emailClinica where e.idEmailClinica =:idEmail");
			query.setParameter("emailClinica", email.getEmailClinica());
			query.setParameter("idEmail", email.getIdEmailClinica());
			
			int qtdLinhas = query.executeUpdate();*/
		
			em.merge(email);
			
		userTransaction.commit();
		
		return true;
	}

	@Override
	public boolean alterarEnderecoClinica(EnderecoClinicaVO endereco) throws Exception {
		
		userTransaction.begin();
			
			/*Query query = em.createQuery("update EnderecoClinicaVO e set e.cidade.idCidade =: idCidade, e.bairroClinica =:bairro"
					+ "e.logradouroClinica =:logradouro, e.complementoClinica =:complemento, e.cepClinica =:cep where e.idEnderecoClinica =:idEndereco");
			query.setParameter("idCidade", endereco.getCidade().getIdCidade());
			query.setParameter("bairro", endereco.getBairroClinica());
			query.setParameter("logradouro", endereco.getLogradouroClinica());
			query.setParameter("complemento", endereco.getComplementoClinica());
			query.setParameter("cep", endereco.getCepClinica());
			query.setParameter("idEndereco", endereco.getIdEnderecoClinica());
			
			int qtdLinhas = query.executeUpdate();*/
			
			em.merge(endereco);
		
		userTransaction.commit();
		
		return true;
	}

	@Override
	public boolean alterarTelefoneClinica(TelefoneClinicaVO telefone) throws Exception {
		
		userTransaction.begin();
			
			/*Query query = em.createQuery("update TelefoneClinicaVO t set t.dddClinica =:ddd, t.telefoneClinica =:telefone, "
					+ "t.tipoTelefone.idTipoTelefone =:tipo where t.idTelefoneClinica =:idTelefone");
			query.setParameter("ddd", telefone.getDddClinica());
			query.setParameter("telefone", telefone.getTelefoneClinica());
			query.setParameter("tipo", telefone.getTipoTelefone().getIdTipoTelefone());
			query.setParameter("idTelefone", telefone.getIdTelefoneClinica());
			
			
			int qtdLinhas = query.executeUpdate();*/
			
			em.merge(telefone);
		
		userTransaction.commit();
		
		return true;
	}

	@Override
	public EmailClinicaVO consultarEmailPorId(Long idEmail) throws Exception {
		
		EmailClinicaVO email = null;
		
		try{
			userTransaction.begin();
			
			Query query = em.createNamedQuery("queryBuscarEmailPorId");
			query.setParameter("idEmail", idEmail);
			
			email = (EmailClinicaVO) query.getSingleResult();
			
			userTransaction.commit();
		}
		catch(NoResultException e){
			
			email = null;
		}
		
		return email;
	}

	@Override
	public TelefoneClinicaVO consultarTelefonePorId(Long idTelefone) throws Exception {
		TelefoneClinicaVO telefone = null;
		
		try{
			
			userTransaction.begin();
			
				Query query = em.createNamedQuery("queryBuscarTelefonePorId");
				query.setParameter("idTelefoneClinica", idTelefone);
				
				telefone = (TelefoneClinicaVO) query.getSingleResult();
			
			userTransaction.commit();
		}
		catch(NoResultException e){
			
			telefone = null;
		}
		
		return telefone;
	}

	@Override
	public EnderecoClinicaVO consultarEnderecoPorId(Long idEndereco) throws Exception {
		EnderecoClinicaVO endereco = null;
		
		try{
			
			userTransaction.begin();
				
				Query query = em.createNamedQuery("queryBsucarEnderecoPorId");
				query.setParameter("idEnderecoClinica", idEndereco);
				
				endereco = (EnderecoClinicaVO) query.getSingleResult();
			
			userTransaction.commit();
		}
		catch(NoResultException e){
			
			endereco = null;
		}
		
		return endereco;
	}

	@Override
	public boolean excluirClinica(ClinicaVO clinica) throws Exception {
		
		userTransaction.begin();
		
			Query query = em.createQuery("update PessoaVO set statusPessoa =:status where idPessoa =:id");
			
			query.setParameter("status", clinica.getStatusPessoa());
			query.setParameter("id", clinica.getIdPessoa());
			
			int qtdLinhas = query.executeUpdate();
			
		userTransaction.commit();
		
		return qtdLinhas > 0;
	}

	@Override
	public boolean excluirEmailClinica(EmailClinicaVO email) throws Exception {
		
		userTransaction.begin();
		
			Query query = em.createQuery("update EmailClinicaVO set status =:status where idEmailClinica =:id");
			query.setParameter("status", email.getStatus());
			query.setParameter("id", email.getIdEmailClinica());
			
			int qtdLinhas = query.executeUpdate();
		
		userTransaction.commit();
		
		return qtdLinhas > 0;
	}

	@Override
	public boolean excluirEnderecoClinica(EnderecoClinicaVO endereco) throws Exception {
		
		userTransaction.begin();
		
			Query query = em.createQuery("update EnderecoClinicaVO set status =:status where idEnderecoClinica =:id");
			query.setParameter("status", endereco.getStatus());
			query.setParameter("id", endereco.getIdEnderecoClinica());
			
			int qtdLinhas = query.executeUpdate();
		
		userTransaction.commit();
		
		return qtdLinhas > 0;
	}

	@Override
	public boolean excluirTelefoneClinica(TelefoneClinicaVO telefone) throws Exception {

		userTransaction.begin();
		
			Query query = em.createQuery("update TelefoneClinicaVO set status =:status where idTelefoneClinica =:id");
			query.setParameter("status", telefone.getStatus());
			query.setParameter("id", telefone.getIdTelefoneClinica());
			
			int qtdLinhas = query.executeUpdate();
		
		userTransaction.commit();
		
		return qtdLinhas > 0;
	}

}
